//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V1.0.0
#include "tm1650_driver.h"

typedef enum
{
    Set_TM1650_Parameter_CMD = 0x48, /*设置系统参数命令*/
    Get_TM1650_KEY_CMD       = 0x4F, /*读取按键值命令*/
}WHT_TM1650_CMD_enum;

typedef enum
{
    Disable_Addr0 = 0x68,
    Disable_Addr1 = 0x6A,
    Disable_Addr2 = 0x6C,
    Disable_Addr3 = 0x6E,
}WHT_TM1650_Addr_enum;

typedef struct
{
    uint8_t Display_Switch     : 1;/*显示状态 1灯开启 0灯关闭*/
    uint8_t Reserve_0          : 1;/*默认0*/
    uint8_t Work_Mode          : 1;/*芯片工作模式，1待机工作模式 0正常工作模式*/
    uint8_t Display_Segment_bit: 1;/*段位个数，1表示7段输出 0表示8段输出*/
    uint8_t Display_Brightness : 3;/*亮度值，范围0~7,1最暗 0最亮*/
    uint8_t Reserve_1          : 1;/*默认0*/
}WHT_TM1650_Parameter_t;

typedef struct
{
    WHT_TM1650_CMD_enum  Set_Parameter; WHT_TM1650_Parameter_t Parameter_Value;
    WHT_TM1650_Addr_enum Addr0;         uint8_t Display_Value0;
    WHT_TM1650_Addr_enum Addr1;         uint8_t Display_Value1;
    WHT_TM1650_Addr_enum Addr2;         uint8_t Display_Value2;
    WHT_TM1650_Addr_enum Addr3;         uint8_t Display_Value3;
    WHT_TM1650_CMD_enum Get_Keys;       uint8_t Keys_Value;
}WHT_TM1650_Buffer_t;




#ifdef TM1650_Soft_I2C
/**********************驱动初始化配置*********************/
static WHT_Soft_I2C_Cache_t wht_cache;

static void WHT_TM1650_Driver_Init(void)
{
    if (WHT_Soft_I2C_BUS1_Init() != 0)
    {
        /* 总线初始化失败 */
        return;
    }
    wht_cache.Cmd_Count = 0;
}
/**********************驱动初始化配置*********************/

/************************** start read & write *******************************/
static void WHT_TM1650_Driver_Write(uint8_t addr_7bit, uint8_t* const input_buf, uint32_t count)
{
    while (WHT_Soft_I2C_BUS1->Mutex == I2C_Lock)//等待互斥锁成功打开
        vTaskDelay(1);
    wht_cache.Addr_7Bit = addr_7bit;
    wht_cache.Dir = Soft_I2C_Write;
    //wht_cache.Cmd[0] = cmd;
    wht_cache.Buffer = input_buf;
    wht_cache.Buffer_Count = count;

    WHT_Soft_I2C_BUS_OPS.Read_Write(WHT_Soft_I2C_BUS1, &wht_cache);
}
static void WHT_TM1650_Driver_Read(uint8_t addr_7bit, uint8_t* const output_buf, uint32_t count)
{
    while (WHT_Soft_I2C_BUS1->Mutex == I2C_Lock)//等待互斥锁成功打开
        vTaskDelay(1);
    wht_cache.Addr_7Bit = addr_7bit;
    wht_cache.Dir = Soft_I2C_Read;
    //wht_cache.Cmd[0] = cmd;
    wht_cache.Buffer = output_buf;
    wht_cache.Buffer_Count = count;

    WHT_Soft_I2C_BUS_OPS.Read_Write(WHT_Soft_I2C_BUS1, &wht_cache);
}
/************************** end read & write ********************************/
#else
/**********************驱动初始化配置*********************/
static SemaphoreHandle_t Tx_xSemaphore;//二值信号量句柄
static SemaphoreHandle_t Rx_xSemaphore;

static WHT_I2C_Cache_t wht_cache;

static void WHT_Tx_Idle_IT_Callback(void);
static void WHT_Rx_Idle_IT_Callback(void);
static void WHT_TM1650_Driver_Init(void)
{
    if (WHT_I2C_BUS1_Init() != 0)
    {
        /* 总线初始化失败 */
        return;
    }
    wht_cache.Cmd_Count = 0;
    wht_cache.Read_Finish_IT_CB = WHT_Rx_Idle_IT_Callback;
    wht_cache.Write_Finish_IT_CB = WHT_Tx_Idle_IT_Callback;

    Tx_xSemaphore = xSemaphoreCreateBinary();
    Rx_xSemaphore = xSemaphoreCreateBinary();
}
/**********************驱动初始化配置*********************/


/************************** start read & write *******************************/
/*发送空闲中断回调函数*/
static void WHT_Tx_Idle_IT_Callback(void)
{
    BaseType_t xHigherPriorityTaskWoken;

    xSemaphoreGiveFromISR(Tx_xSemaphore, &xHigherPriorityTaskWoken);//释放信号量
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
/*接收空闲中断回调函数*/
static void WHT_Rx_Idle_IT_Callback(void)
{
    BaseType_t xHigherPriorityTaskWoken;

    xSemaphoreGiveFromISR(Rx_xSemaphore, &xHigherPriorityTaskWoken);//释放信号量
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
static void WHT_TM1650_Driver_Write(uint8_t addr_7bit, uint8_t* const input_buf, uint32_t count)
{
    while (WHT_I2C_BUS1->Mutex == I2C_Lock)//等待互斥锁成功打开
        vTaskDelay(1);
    wht_cache.Addr_7Bit = addr_7bit;
    wht_cache.Dir = I2C_Write;
    //wht_cache.Cmd[0] = cmd;
    wht_cache.Buffer = input_buf;
    wht_cache.Buffer_Count = count;

    TickType_t Tick_Count = count * 9 * 1000  / WHT_I2C_BUS1->Config.I2C_Rate_Hz / portTICK_RATE_MS;//单位ms/Tick
    if (Tick_Count)
        WHT_I2C_BUS_OPS.Read_Write_DMA(WHT_I2C_BUS1, &wht_cache);
    else
        WHT_I2C_BUS_OPS.Read_Write_IT(WHT_I2C_BUS1, &wht_cache);
    
    if (WHT_I2C_BUS1->Mutex == I2C_Unlock)//传输结束
    {
        /*用户可以加入判断是否有错误相关代码*/
    }
    else
        xSemaphoreTake(Tx_xSemaphore, portMAX_DELAY);//等待信号量
}
static void WHT_TM1650_Driver_Read(uint8_t addr_7bit, uint8_t* const output_buf, uint32_t count)
{
    while (WHT_I2C_BUS1->Mutex == I2C_Lock)//等待互斥锁成功打开
        vTaskDelay(1);
    wht_cache.Addr_7Bit = addr_7bit;
    wht_cache.Dir = I2C_Read;
    //wht_cache.Cmd[0] = cmd;
    wht_cache.Buffer = output_buf;
    wht_cache.Buffer_Count = count;

    TickType_t Tick_Count = count * 9 * 1000  / WHT_I2C_BUS1->Config.I2C_Rate_Hz / portTICK_RATE_MS;//单位ms/Tick
    if (Tick_Count)
        WHT_I2C_BUS_OPS.Read_Write_DMA(WHT_I2C_BUS1, &wht_cache);
    else
        WHT_I2C_BUS_OPS.Read_Write_IT(WHT_I2C_BUS1, &wht_cache);
    
    if (WHT_I2C_BUS1->Mutex == I2C_Unlock)//传输结束
    {
        /*用户可以加入判断是否有错误相关代码*/
    }
    else
        xSemaphoreTake(Rx_xSemaphore, portMAX_DELAY);//等待信号量
}
/************************** end read & write ********************************/
#endif /*TM1650_Soft_I2C*/


static uint8_t WHT_TM1650_Driver_Scan_I2C_Slave_Count(void)
{
#ifdef TM1650_Soft_I2C
    return WHT_Soft_I2C_BUS_OPS.Scan_Mount_Count(WHT_Soft_I2C_BUS1);
#else
    return WHT_I2C_BUS_OPS.Scan_Mount_Count(WHT_I2C_BUS1);
#endif // TM1650_Soft_I2C
}





static WHT_TM1650_Buffer_t WHT_TM1650_Buffer;

/*TM1650类IIC通信和它没有IIC地址故以下通信上看起来有点怪*/
/* 设置亮度 */
static void WHT_TM1650_Set_Brightness(WHT_TM1650_State_enum brightness)
{
    WHT_TM1650_Buffer.Parameter_Value.Display_Switch = brightness == TM1650_Brightness_0 ? 0 : 1;
    WHT_TM1650_Buffer.Parameter_Value.Display_Brightness = brightness >= TM1650_Brightness_8 ? 0 : brightness;

    WHT_TM1650_Driver_Write(WHT_TM1650_Buffer.Set_Parameter >> 1, (uint8_t*)&WHT_TM1650_Buffer.Parameter_Value, 1);
}
/* 设置段码 */
static void WHT_TM1650_Set_Segment(WHT_TM1650_State_enum segment)
{
    WHT_TM1650_Buffer.Parameter_Value.Display_Segment_bit = segment;

    WHT_TM1650_Driver_Write(WHT_TM1650_Buffer.Set_Parameter >> 1, (uint8_t*)&WHT_TM1650_Buffer.Parameter_Value, 1);
}
/* 设置模式 */
static void WHT_TM1650_Set_mode(WHT_TM1650_State_enum mode)
{
    WHT_TM1650_Buffer.Parameter_Value.Work_Mode = mode;
    WHT_TM1650_Driver_Write(WHT_TM1650_Buffer.Set_Parameter >> 1, (uint8_t*)&WHT_TM1650_Buffer.Parameter_Value, 1);
}
/* 设置显示值 */
static void WHT_TM1650_Set_Display_Value(uint32_t value_32bit)
{
    typedef struct
    {
        uint8_t Display_Value0;
        uint8_t Display_Value1;
        uint8_t Display_Value2;
        uint8_t Display_Value3;
    }LSB_t; //小端平台

    typedef struct
    {
        uint8_t Display_Value3;
        uint8_t Display_Value2;
        uint8_t Display_Value1;
        uint8_t Display_Value0;
    }MSB_t;//大端平台

    /* 注意大小端问题 */
#if 1
    #define Display_Value_P ((LSB_t*)&value_32bit)
#else
    #define Display_Value_P ((LSB_t*)&value_32bit)
#endif

    if (Display_Value_P->Display_Value0 != WHT_TM1650_Buffer.Display_Value0)
    {
        WHT_TM1650_Buffer.Display_Value0 = Display_Value_P->Display_Value0;
        WHT_TM1650_Driver_Write(WHT_TM1650_Buffer.Addr0 >> 1, &WHT_TM1650_Buffer.Display_Value0, 1);
    }
    if (Display_Value_P->Display_Value1 != WHT_TM1650_Buffer.Display_Value1)
    {
        WHT_TM1650_Buffer.Display_Value1 = Display_Value_P->Display_Value1;
        WHT_TM1650_Driver_Write(WHT_TM1650_Buffer.Addr1 >> 1, &WHT_TM1650_Buffer.Display_Value1, 1);
    }
    if (Display_Value_P->Display_Value2 != WHT_TM1650_Buffer.Display_Value2)
    {
        WHT_TM1650_Buffer.Display_Value2 = Display_Value_P->Display_Value2;
        WHT_TM1650_Driver_Write(WHT_TM1650_Buffer.Addr2 >> 1, &WHT_TM1650_Buffer.Display_Value2, 1);
    }
    if (Display_Value_P->Display_Value3 != WHT_TM1650_Buffer.Display_Value3)
    {
        WHT_TM1650_Buffer.Display_Value3 = Display_Value_P->Display_Value3;
        WHT_TM1650_Driver_Write(WHT_TM1650_Buffer.Addr3 >> 1, &WHT_TM1650_Buffer.Display_Value3, 1);
    }
}
/* 获取按键值 */
static uint8_t WHT_TM1650_Get_Keys_Value(void)
{
    /* 这个地方的读取，会先写按键地址，然后写0个命令，写按键地址如果没有应答的话就嗝屁了 */
    WHT_TM1650_Driver_Read(WHT_TM1650_Buffer.Get_Keys >> 1, &WHT_TM1650_Buffer.Keys_Value, 1);
    return WHT_TM1650_Buffer.Keys_Value;
}



static void WHT_TM1650_Init(void)
{
    WHT_TM1650_Driver_Init();

    memset(&WHT_TM1650_Buffer, 0, sizeof(WHT_TM1650_Buffer));

    WHT_TM1650_Buffer.Set_Parameter = Set_TM1650_Parameter_CMD;
    WHT_TM1650_Buffer.Addr0         = Disable_Addr0;
    WHT_TM1650_Buffer.Addr1         = Disable_Addr1;
    WHT_TM1650_Buffer.Addr2         = Disable_Addr2;
    WHT_TM1650_Buffer.Addr3         = Disable_Addr3;
    WHT_TM1650_Buffer.Get_Keys      = Get_TM1650_KEY_CMD;

    /* MT1650最大60毫秒内部上电初始化,在芯片上电内部初始化时如果IIC进行通信会导致MT1650死机 */
    WHT_Delay_ms(60);
    WHT_TM1650_Driver.WHT_Set_Brightness(TM1650_Brightness_0); // 关灯
    WHT_TM1650_Driver.WHT_Set_Segment(TM1650_Segment_8bit);    // 默认8段
    WHT_TM1650_Driver.WHT_Set_mode(TM1650_Default_Mode);       // 正常模式
    WHT_TM1650_Driver.WHT_Set_Display_Value(0);                // 所有全关
}



const WHT_TM1650_Driver_t WHT_TM1650_Driver =
{
    .WHT_Init                 = WHT_TM1650_Init,
    .WHT_Scan_I2C_Slave_Count = WHT_TM1650_Driver_Scan_I2C_Slave_Count,
    .WHT_Set_Brightness       = WHT_TM1650_Set_Brightness,
    .WHT_Set_Segment          = WHT_TM1650_Set_Segment,
    .WHT_Set_mode             = WHT_TM1650_Set_mode,
    .WHT_Set_Display_Value    = WHT_TM1650_Set_Display_Value,
    .WHT_Get_Kyes_Value       = WHT_TM1650_Get_Keys_Value,
};
